Exceptions

Exceptions are caused by internal or external sources such as from a hardware interrupt or by trying to read or write an invalid memory location.

When an exception occurs the processor’s state is preserved and the processor enters an exception mode so the exception can be handled. The saved state enables the processor to return to the original program and resume its execution.

Exception Actions

These are the steps the CPU does automatically when there is an exception.

  • Saves address of next instruction to the mode’s R14
  • Saves CPSR to mode’s SPSR
  • Changes the mode
  • Disables interrupts
    • All exceptions disable IRQ interrupts
    • FIQ exception also disable FIQ interrupts
  • Loads PC with the modes vector address
  • Begins executing at new location

Returning from Exception

Here are some examples on how to return from an exception when not using a stack.

Action Instruction
Returning from SWI or Undef MOVS pc, r14
Returning from IRQ, FIQ, or prefetch SUBS pc, r14, #4
Returning from Data Abort SUBS pc, r14, #8
  • The ‘s’ at the end of the opcode means special instruction when the destination is the pc
  • It sets the PC and restores the CPSR from SPSR in on instruction

Stack Handling

Stacks can grow either up or down in memory. And the stack pointer can point to either the last filled location or the next empty location.

By convention, the most common is to grow down in memory and for the stack pointer to point to the last filled location.

Saving all the registers to the current stack:

STMFD r13!, {r0-r12, r14}

Returning from an exception and handling a stack at the same time:

LDMFD r13!, {r0-r12, pc}^
  • R13 is the mode’s stack pointer. It must be setup at startup.
  • R14 is adjusted before saving it to the stack.
  • ‘!’ means increment or decrement register
  • ‘^’ means restore CPSR
  • R14 is restored to the pc on return.

Program Counter (PC)

Writing to the PC directly causes the intruction stream to immediately start executing at the new location. It can be used to jump to a new location.

To use writing to the PC as a jump to a subroutine, we need to save the PC to the LR before we change the PC. Because of the way the pipeline works, the address in the PC is actually +8 from the instruction we at.

This works out well, since the LR will then have the address after the next instruction. Which is the right address for the returning subroutine to use.

MOV LR, PC
LDR PC, =subroutine

Reset Exeception

The Reset exception occurs whenever the reset pin on the processor is asserted then de-asserted.

State on entering the exception:

R14_svc = random value
SPSR_svc = random value
CPSR = Supervisor mode, ARM state, IRQ off, FIQ off
PC = 0x00000000

Returning from a reset doesn’t make sense and is not possible.

Undefined Exception

The Undefined exception occurs when the processor tries to execute an unknown instruction. The processor will first wait to see if the co-processor will handle it. If not the exception occurs.

The undefined exception is often used to emulate the use of a coprocessor such as hardware floating point. On a system without a floating point coprocessor, the floating point instruction cause exceptions. Exception handled then runs code that emulates the action of the floating point instruction and then returns the value as though there was a floating point coprocessor.

State on entering the exception:

R14_undef = address of next instruction after undef instruction
SPSR_undef = CPSR
CPSR = CPSR with Undef mode, ARM state, IRQ off
PC = 0x00000004

To return to the next instruction after handling the exception use:

MOVS PC, R14

SWI - Software Interrupt Exception

The SWI exception occurs whenever the processor executes a SWI instruction. The SWI instructions and their exceptions are often used to implement system APIs that access priviledged features of the system.

State on entering the exception:

R14_svc = address of next instruction after the SWI instruction
SPSR_svc = CPSR
CPSR = CPSR with Supervisor mode, ARM state, IRQ off
PC = 0x00000008

To return to the next instruction after handling the exception use:

MOVS PC, R14

Prefetch Abort - Instruction Fetch Memory Abort

A memory abort is signaled by the memory system. It marks the instruction as invalid. However the actual abort only occurs if the processor tries to execute the instruction. If a branch occurs before the instruction is run, then the abort does not happen.

State on entering the exception:

R14_abt = address of next of the abort instruction + 4
SPSR_abt = CPSR
CPSR = CPSR with Abort mode, ARM state, IRQ off
PC = 0x0000000C

To rerun the instruction, assuming the instruction is now valid:

SUBS PC, R14, #4

To return to the next instruction instead of rerunning the instruction:

MOVS PC, R14

Data Abort - Data Access Memory Abort

A memory abort is signaled by the memory system. It marks the data as invalid. The abort happens before anything else can change the state of the CPU.

Whether or not a data abort changes the memory depends on the memory system. If the location is not writable, then no change occurs. However if it is writable then the results are unpredictable.

State on entering the exception:

R14_abt = address of next of the abort instruction + 8
SPSR_abt = CPSR
CPSR = CPSR with Abort mode, ARM state, IRQ off
PC = 0x00000010

If the reason fro the abort has been fixed and you want to rerun the instruction that aborted use:

SUBS PC, R14, #8

To return and skip the instruction that abort and instead resume at the next instruction use:

SUBS PC, R14, #4

IRQ - Interrupt Request Exception

An IRQ exception is caused by asserting the IRQ pin on the processor. The IRQ exception as a lower priority then an FIQ exception. The IRQ is masked during an FIQ exception.

IRQ interrupts are disabled by setting the I bit in the CPSR and are enabled by clearing the I bit.

The processor checks for IRQ between executing instructions. That is, at the boundary between instructions.

State on entering the exception:

R14_irq = address of the next instruction + 4
SPSR_irq = CPSR
CPSR = CPSR with Abort mode, ARM state, IRQ off
PC = 0x00000018

To return and resume executing the interrupted code after handling the IRQ use:

SUBS PC, R14, #4

FIQ - Fast Interrupt Request Exception

An FIQ exception is caused by asserting the FIQ pin on the processor.

FIQ was designed to support low latency operations such as data transfer operations without needed to save registers. It reduces the cost of context switching for the operations.

FIQ are disabled by setting the F bit in the CPSR and are enabled by clearing the F bit. The F bit can only be changed from a priviledged mode.

The processor checks for FIQ between instructions.

State on entering the exception:

R14_fiq = address of the next instruction + 4
SPSR_fiq = CPSR
CPSR = CPSR with Abort mode, ARM state, IRQ off, FIQ off
PC = 0x0000001C

To resume the interrupted code after handling the interrupt use:

SUBS PC, R14, #4

Note

The vector for FIQ is the last vector in the exception vector table. That allows the FIQ exception handler to start directly at the vector address without needed to branch.

Exception Priorities

Priorty Exception
1 Reset
2 Data abort
3 FIQ
4 IRQ
5 Prefetch abort
6 Undefined and SWI